package com.atguigu.search.thread;

import java.util.concurrent.*;

public class ThreadTest {
    public static ExecutorService service= Executors.newFixedThreadPool(10);

    /**
     * CompletableFuture异步编排
     *
     * @param args
     * @throws ExecutionException
     * @throws InterruptedException
     */
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("线程开启了");
//        CompletableFuture.runAsync 没有返回结果

     /*   CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> {
            System.out.println("当前线程为：" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println(i);
        }, service);
*/
        /**
         * CompletableFuture.supplyAsync 有返回结果
         */

//        CompletableFuture<Integer> supplyAsync = CompletableFuture.supplyAsync(() -> {
//            System.out.println("当前线程为：" + Thread.currentThread().getId());
//            int i = 10 / 0;
//            System.out.println(i);
//            return i;
//        }, service).whenComplete((res,exception)->{
//        //TODO whenComplete在线程完成时回调，不能改变结果
//
//            System.out.println("异步结果完成了结果为："+res+"异常为："+exception);
//        }).exceptionally(throwable -> {
//            return 10;
//        });



//        CompletableFuture<Integer> supplyAsync = CompletableFuture.supplyAsync(() -> {
//            System.out.println("当前线程为：" + Thread.currentThread().getId());
//            int i = 10 / 0;
//            System.out.println(i);
//            return i;
//        }, service).handle((res,throwable)->{
//            //TODO handle 最终处理结果 可以对结果进行操作并返回
//            if (res!=null){
//                return res*2;
//            }
//            if (throwable!=null){
//                return 0;
//            }
//            return 0;
//        });
        /*
        线程串行化
        thenRunAsync 直接启动第二线程，不用上一个线程的返回结果
        thenAcceptAsync 拿到上一个线程执行的结果，再执行第二个线程
        thenApplyAsync  拿到上一个线程执行的结果 并且返回本次处理的结果
         */

//        CompletableFuture.supplyAsync(() -> {
//            System.out.println("当前线程为：" + Thread.currentThread().getId());
//            int i = 10 / 2;
//            System.out.println(i);
//            return i;
//        }, service).thenRunAsync(()->{
//            System.out.println("线程2启动了");
//        },service);

//        CompletableFuture.supplyAsync(() -> {
//            System.out.println("当前线程为：" + Thread.currentThread().getId());
//            int i = 10 / 2;
//            System.out.println(i);
//            return i;
//        }, service).thenAcceptAsync((res)->{
//            System.out.println("线程1的结果为"+res);
//            System.out.println("线程2启动了");
//        },service);

//        CompletableFuture<String> applyAsync = CompletableFuture.supplyAsync(() -> {
//            System.out.println("当前线程为：" + Thread.currentThread().getId());
//            int i = 10 / 2;
//            System.out.println(i);
//            return i;
//        }, service).thenApplyAsync((res) -> {
//            System.out.println("线程1的结果为" + res);
//            System.out.println("线程2启动了");
//            return "这是线程2的返回结果" + res;
//        }, service);
//        String s = applyAsync.get();

        /**
         * 两个异步任务完成后 再执行
         * runAfterBothAsync 无返回结果，不用前两个线程的返回结果
         * thenAcceptBothAsync 无返回结果，能够接受前两个线程的结果
         * thenCombineAsync 有返回结果 能够接受前两个线程的结果
         *
         * 两个中有一个完成后再执行
         *runAfterEitherAsync 无返回结果，不用返回结果
         *acceptEitherAsync 无返回结果，接受已完成线程的结果
         *applyToEitherAsync 有返回结果 能够接受前面的结果
         */
//        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
//            System.out.println("线程1为：" + Thread.currentThread().getId());
//            return 1;
//        }, service);
//        CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
//            try {
//                Thread.sleep(3000);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            System.out.println("线程2为：" + Thread.currentThread().getId());
//            return 2;
//        }, service);
//        future1.runAfterBothAsync(future2,()->{
//            System.out.println("线程3");
//        },service);

//        future1.thenAcceptBothAsync(future2,(f1,f2)->{
//            System.out.println("线程3,"+f1+";"+f2);
//        },service);
//        CompletableFuture<Integer> future = future1.thenCombineAsync(future2, (f1, f2) -> {
//            System.out.println("线程3," + f1 + ";" + f2);
//            return 3;
//        }, service);
//            future1.runAfterEitherAsync(future2,()->{
//                System.out.println("线程3完成了");
//            },service);

//        future1.acceptEitherAsync(future2,(res)->{
//            System.out.println("线程3完成了"+res);
//        },service);
//        CompletableFuture<Integer> future = future1.applyToEitherAsync(future2, (res) -> {
//            System.out.println("线程3完成了" + res);
//            return 3;
//        }, service);


//        Integer integer = supplyAsync.get();
//        Integer integer = future.get();

        /**
         * 多任务组合
         * CompletableFuture.allOf 所有任务完成
         * CompletableFuture.anyOf  任意一个完成
         */
        CompletableFuture<String> productImg = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("商品图片");
            return "商品图片";
        }, service);
        CompletableFuture<String> productAttr = CompletableFuture.supplyAsync(() -> {
            System.out.println("商品属性");
            return "商品属性";
        }, service);
        CompletableFuture<String> productPrice = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("商品价格");
            return "商品价格";
        }, service);
//        CompletableFuture<Void> allOf = CompletableFuture.allOf(productImg, productAttr, productPrice);
//        allOf.get();
        CompletableFuture<Object> anyOf = CompletableFuture.anyOf(productImg, productAttr, productPrice);


        System.out.println("线程结束了"+anyOf.get());
    }

    public static void Thread(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main开始了");
        /*Thread01 extends Thread

        Thread01 thread01 = new Thread01();
        thread01.start();*/

        /**
         * Runable01 implements Runnable

        Runable01 runable01 = new Runable01();
        Thread thread = new Thread(runable01);
        thread.start();
         */

        /**
         * Callable01 implements Callable
         * Callable01 callable01 = new Callable01();
         *         FutureTask<Integer> futureTask = new FutureTask<>(callable01);
         *         Thread thread = new Thread(futureTask);
         *         thread.start();
         *         //阻塞等待方法执行完以后拿到返回结果
         *         Integer integer = futureTask.get();
         */
        /**
         * ExecutorService service= Executors.newFixedThreadPool(10);
         * 使用线程池
         * service.execute(new Runable01());
         */

        /**
         * 使用原生创建线程池
         */
        /**
         * 七大参数
         * corePoolSize 核心线程数：一直存在 线程池创建好以后，就会一直存在指定数量的线程，等待接受处理异步任务
         * maximumPoolSize 最大线程数
         * keepAliveTime 存活时间 如果空闲的线程大于核心线程数，空闲时间大于指定的时间，会释放线程
         * unit 存货时间的时间单位
         * BlockingQueue<Runnable> workQueue, 阻塞队列，任务很多时，未能够即使处理的任务会放在队列里，有线程空闲时，会从队列中取出任务继续执行
         * threadFactory创建线程工厂
         * handler 如果队列满了，按照我们指定的拒绝策略执行任务
         *
         * 工作顺序
         *  线程池创建，准备好core数量的核心线程，准备接受任务
         *      core满了以后，再进来的任务进入阻塞队列，有空闲的core时，会从队列中领取任务
         *      阻塞队列满了会创建新的线程，最大数量开到max指定的数量
         *      max满了以后用handler拒绝任务
         *      max都执行完以后，keepAliveTime后把空闲的线程释放
         */
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5,
                200,
                10,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(100000),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());


        System.out.println("main结束了");
    }
    public static class Thread01 extends Thread{
        @Override
        public void run() {
            System.out.println("当前线程为："+Thread.currentThread().getId());
            int i=10/2;
            System.out.println(i);
        }
    }
    public static class Runable01 implements Runnable{

        @Override
        public void run() {
            System.out.println("当前线程为："+Thread.currentThread().getId());
            int i=10/2;
            System.out.println(i);
        }
    }

    public static class Callable01 implements Callable<Integer>{

        @Override
        public Integer call() throws Exception {
            System.out.println("当前线程为："+Thread.currentThread().getId());
            int i=10/2;
            System.out.println(i);
            return i;
        }
    }
}
